#include "StdAfx.h"
#include "Rectangle.h"

using namespace System;

namespace ManagedSail
{
	SageRectangle^ SageRectangle::operator+ (SageRectangle^ a, SageRectangle^ b)
	{
		SageRectangle^ res = gcnew SageRectangle();
		res->x = a->x + b->x;
		res->y = a->y + b->y;
		res->width = a->width + b->width;
		res->height = a->height + b->height;
		return res;
	}

	SageRectangle^ SageRectangle::operator/ (SageRectangle^ a, SageRectangle^ b)
	{
		SageRectangle^ res = gcnew SageRectangle();
		res->left = (a->x - b->x)/(float)b->width;
		res->right = (a->x + a->width - b->x)/(float)b->width;
		res->bottom = (a->y - b->y)/(float)b->height;
		res->top = (a->y + a->height - b->y)/(float)b->height;

		return res;
	}

	SageRectangle^ SageRectangle::operator/ (SageRectangle^ a, float val)
	{
		SageRectangle^ res = gcnew SageRectangle();
		res->x = (int)(Math::Floor(a->x/val+0.5));
		res->y = (int)(Math::Floor(a->y/val+0.5));
		res->width = (int)(Math::Floor(a->width/val+0.5));
		res->height = (int)(Math::Floor(a->height/val+0.5));

		return res;
	}

	SageRectangle^ SageRectangle::operator* (SageRectangle^ a, SageRectangle^ b)
	{
		SageRectangle^ res = gcnew SageRectangle();
		res->x = (int)(Math::Floor(a->width*b->left+0.5));
		res->y = (int)(Math::Floor(a->height*b->bottom+0.5));
		res->width = (int)(Math::Floor(a->width*b->right+0.5)) - res->x;
		res->height = (int)(Math::Floor(a->height*b->top+0.5)) - res->y;
		res->Translate(a->x, a->y);

		return res;
	}

	void SageRectangle::UpdateBoundary()
	{
		left = x;
		right = x + width;
		bottom = y;
		top = y + height;
	}

	void SageRectangle::UpdateBoundary(SageRectangle^ rect)
	{
		left = rect->x;
		right = rect->x + rect->width;
		bottom = rect->y;
		top = rect->y + rect->height;
	}

	// move the origin to the lowerleft corner of rect
	void SageRectangle::MoveOrigin(SageRectangle^ rect)
	{
		Translate(-rect->x, -rect->y);
	}

	void SageRectangle::Scale(float sx, float sy)
	{
		left *= sx;
		right *= sx;
		bottom *= sy;
		top *= sy;
	}

	void SageRectangle::Translate(int dx, int dy)
	{
		x += dx;
		y += dy;
	}

	void SageRectangle::Translate(SageRectangle^ rect)
	{
		Translate(rect->x, rect->y);
	}

	void SageRectangle::Shrink(float dx, float dy)
	{	
		left += dx;
		right -= dx;
		bottom += dy;
		top -= dy;
	}	

	void SageRectangle::Locate()
	{
		x = (int)Math::Floor(left*width/(right-left)+0.5);
		y = (int)Math::Floor(bottom*height/(top-bottom)+0.5);
	}

	/*
	int SageRectangle::mask(SageRectangle^ rect)
	{
	float width = right - left;
	float height = top - bottom;

	SageRectangle tmpRect = rect;
	tmpRect.scale(width, height);
	tmpRect.Translate(left, bottom);
	*this = tmpRect;

	return 0;
	}
	*/


	void SageRectangle::Normalize(SageRectangle^ rect)
	{	
		if (rect->left == rect->right || rect->bottom == rect->top) {
			throw gcnew Exception("Can't divide by 0 : fail to normalize rect");
		}	

		float width = rect->right - rect->left;
		float height = rect->top - rect->bottom;

		MoveOrigin(rect);

		left /= width;
		right /= width;
		bottom /= height;
		top /= height;
	}	

	void SageRectangle::Normalize(float x, float y)
	{	
		if (x == 0 || y == 0) {
			throw gcnew Exception("Can't divide by 0 : fail to normalize rect");
		}	

		left /= x;
		right /= x;
		bottom /= y;
		top /= y;
	}	

	bool SageRectangle::IsOverLapX(float l, float r, SageRectangle^ common) 
	{
		if (l <= right && r >= left) {
			common->left = Math::Max(l, left);
			common->right = Math::Min(r, right);
			return true;
		}
		else 
			return false;
	}

	bool SageRectangle::IsOverLapY(float b, float t, SageRectangle^ common) 
	{
		if (b <= top && t >= bottom) {
			common->bottom = Math::Max(b, bottom);
			common->top = Math::Min(t, top);
			return true;
		}
		else 
			return false;
	}

	bool SageRectangle::IsOverLap(float l, float r, float b, float t, SageRectangle^ common) 
	{
		return (IsOverLapX(l, r, common) && IsOverLapY(b, t, common));
	}	

	bool SageRectangle::IsOverLapX(int x2, int w2, SageRectangle^ common) 
	{
		int r1 = x+width-1;
		int r2 = x2+w2-1;

		if (x2 <= r1 && r2 >= x) {
			common->x = Math::Max(x2, x);
			int rCommon = Math::Min(r1, r2);
			common->width = rCommon-common->x+1;
			return true;
		}
		else 
			return false;
	}

	bool SageRectangle::IsOverLapY(int y2, int h2, SageRectangle^ common) 
	{
		int t1 = y+height-1;
		int t2 = y2+h2-1;

		if (y2 <= t1 && t2 >= y) {
			common->y = Math::Max(y2, y);
			int tCommon = Math::Min(t1, t2);
			common->height = tCommon-common->y+1;
			return true;
		}
		else 
			return false;
	}

	bool SageRectangle::IsOverLap(SageRectangle^ rect, SageRectangle^ com)
	{
		return (IsOverLapX(rect->x, rect->width, com) && IsOverLapY(rect->y, rect->height, com));
	}

	bool SageRectangle::IsOverLap(SageRectangle^ rect)
	{
		SageRectangle^ dummy;
		return IsOverLap(rect, dummy);
	}

	bool SageRectangle::IsInRect(float x, float y) 
	{
		UpdateBoundary();

		if (left <= x&& right >= x&& bottom <= y&& top >= y)
			return true;
		else
			return false;
	}	

	bool SageRectangle::IsInRect(SageRectangle^ rect) 
	{
		UpdateBoundary();
		rect->UpdateBoundary();

		if (x <= rect->left&& right >= rect->right&& bottom <= rect->bottom&& top >= rect->top)
			return true;
		else
			return false;
	}
}